# pragma once

# include "cpp_tools_Headers.h"
# include "serialib.h"
# include "Clock.h"

namespace cpp_tools
{
    template<typename T>
    class UartVectorPort 
    {
    public:
        // 定义帧头和帧尾，用于帧同步
        const uint8_t FRAME_HEADER = 0xAA;
        const uint8_t FRAME_TAIL = 0x55;

        // 定义数据类型标识
        enum class DataType 
        {
            INT = 0x00,
            INT64 = 0x01,
            FLOAT = 0x10,
            DOUBLE = 0x11,
        };
    private:
        serialib serial;
        std::string portName;
        unsigned int baudRate;
        bool isConnected;
    
        // 计算简单校验和
        uint8_t calculateChecksum(const uint8_t* data, size_t length) {
            uint8_t checksum = 0;
            for (size_t i = 0; i < length; ++i) {
                checksum ^= data[i];
            }
            return checksum;
        }
    
    public:
        // 构造函数
        UartVectorPort(const std::string& port, unsigned int baud) 
            : portName(port), baudRate(baud), isConnected(false) 
        {
            open();
        }
    
        // 析构函数
        ~UartVectorPort() 
        {
            close();
        }
    
        // 打开串口连接
        bool open() {
            if (isConnected) return true;
    
            if (serial.openDevice(portName.c_str(), baudRate) != 1) {
                std::cerr << "无法打开串口: " << portName << std::endl;
                return false;
            }
    
            isConnected = true;
            return true;
        }
    
        // 关闭串口连接
        void close() {
            if (isConnected) {
                serial.closeDevice();
                isConnected = false;
            }
        }

        /// @brief 发送Eigen向量
        /// @param vec 
        /// @return 
        /// 1: 发送成功
        /// 
        /// 0：发送失败
        /// 
        /// -1：串口未连接
        /// 
        /// -2：无效的向量大小
        /// 
        /// -3：不支持的数据类型
        int sendVector(const Eigen::Matrix<T, Eigen::Dynamic, 1>& vec) {
            if (!isConnected) 
            {
                // std::cerr << "串口未连接" << std::endl;
                return -1;
            }
    
            // 获取向量大小
            size_t size = vec.size();
            if (size <= 0 || size > 0xFFFF) // 限制最大尺寸为65535
            {
                // std::cerr << "无效的向量大小" << std::endl;
                return -2;
            }
    
            // 确定数据类型
            uint8_t dataType;
            if (std::is_same<T, int>::value) 
            {
                dataType = static_cast<int>(DataType::INT);
            } 
            else if (std::is_same<T, int64_t>::value) 
            {
                dataType = static_cast<int>(DataType::INT64);
            } 
            else if (std::is_same<T, float>::value) 
            {
                dataType = static_cast<int>(DataType::FLOAT);
            } 
            else if (std::is_same<T, double>::value) 
            {
                dataType = static_cast<int>(DataType::DOUBLE);
            } 
            else 
            {
                // std::cerr << "不支持的数据类型" << std::endl;
                return -3;
            }
    
            // 计算总数据长度
            size_t dataLength = size * sizeof(T);
            size_t frameSize = 1 + 2 + 1 + dataLength + 1 + 1; // 帧头 + 大小(2字节) + 类型 + 数据 + 校验和 + 帧尾
    
            // 分配缓冲区
            uint8_t* buffer = new uint8_t[frameSize];
            size_t index = 0;
    
            // 填充帧头
            buffer[index++] = FRAME_HEADER;
    
            // 填充大小（2字节，小端模式）
            buffer[index++] = static_cast<uint8_t>(size & 0xFF);
            buffer[index++] = static_cast<uint8_t>((size >> 8) & 0xFF);
    
            // 填充数据类型
            buffer[index++] = dataType;
    
            // 填充数据
            std::memcpy(&buffer[index], vec.data(), dataLength);
            index += dataLength;
    
            // 计算并填充校验和
            uint8_t checksum = calculateChecksum(buffer + 1, index - 1); // 不包含帧头
            buffer[index++] = checksum;
    
            // 填充帧尾
            buffer[index++] = FRAME_TAIL;
    
            // 发送数据
            size_t bytesSent = serial.writeBytes(buffer, frameSize);
            delete[] buffer;
    
            return bytesSent > 0;
        }
    
        /// @brief 获取向量
        /// @param vec 
        /// @param timeOut_ms 接收帧头的超时时间 (s)
        /// @param readTimeOut_ms 每次读取时的超时时间 (ms)
        /// @return 
        /// 1: 读取成功
        /// 
        /// 0：读取失败
        /// 
        /// -1：串口未连接
        int receiveVector(Eigen::Matrix<T, Eigen::Dynamic, 1>& vec, unsigned int timeOut_ms = 5, unsigned int readTimeOut_ms = 5) 
        {
            if (!isConnected) 
            {
                // std::cerr << "串口未连接" << std::endl;
                return -1;
            }
    
            uint8_t byte;
            size_t bytesRead;
            cpp_tools::clock clock;
    
            // 寻找帧头
            while (1) 
            {
                bytesRead = serial.readBytes(&byte, 1, 1); // 每次尝试等待1ms
                if (bytesRead == 1 && byte == FRAME_HEADER) {
                    break;
                }
                
                // 检查超时
                if (clock.toc(0) > timeOut_ms) {
                    // std::cerr << "接收超时" << std::endl;
                    return 0;
                }
            } 
    
            // 读取大小（2字节，小端模式）
            uint8_t sizeBytes[2];
            bytesRead = serial.readBytes(sizeBytes, 2, readTimeOut_ms);
            if (bytesRead != 2) 
            {
                // std::cerr << "读取大小失败" << std::endl;
                return 0;
            }
            size_t size = static_cast<size_t>(sizeBytes[0]) | (static_cast<size_t>(sizeBytes[1]) << 8);
    
            if (size <= 0 || size > 0xFFFF) 
            {
                // std::cerr << "收到无效的向量大小" << std::endl;
                return 0;
            }
    
            // 读取数据类型
            uint8_t dataType;
            bytesRead = serial.readBytes(&dataType, 1, readTimeOut_ms);
            if (bytesRead != 1) 
            {
                // std::cerr << "读取数据类型失败" << std::endl;
                return 0;
            }
    
            // 检查数据类型是否匹配
            if ((std::is_same<T, int>::value && dataType != static_cast<int>(DataType::INT)) ||
                (std::is_same<T, int64_t>::value && dataType != static_cast<int>(DataType::INT64)) ||
                (std::is_same<T, float>::value && dataType != static_cast<int>(DataType::FLOAT)) ||
                (std::is_same<T, double>::value && dataType != static_cast<int>(DataType::DOUBLE))) 
            {
                // std::cerr << "数据类型不匹配" << std::endl;
                return 0;
            }
    
            // 读取数据
            size_t dataLength = size * sizeof(T);
            uint8_t* dataBuffer = new uint8_t[dataLength];
            bytesRead = serial.readBytes(dataBuffer, dataLength, readTimeOut_ms);
            if (bytesRead != dataLength) 
            {
                // std::cerr << "读取数据失败" << std::endl;
                delete[] dataBuffer;
                return 0;
            }

            // 读取校验和
            uint8_t receivedChecksum;
            bytesRead = serial.readBytes(&receivedChecksum, 1, readTimeOut_ms);
            if (bytesRead != 1) 
            {
                // std::cerr << "读取校验和失败" << std::endl;
                delete[] dataBuffer;
                return 0;
            }
    
            // 验证校验和
            uint8_t checksumBuffer[3 + dataLength]; // 大小(2) + 类型(1) + 数据
            std::memcpy(checksumBuffer, sizeBytes, 2);
            checksumBuffer[2] = dataType;
            std::memcpy(checksumBuffer + 3, dataBuffer, dataLength);
            
            uint8_t calculatedChecksum = calculateChecksum(checksumBuffer, 3 + dataLength);
            if (calculatedChecksum != receivedChecksum) 
            {
                // std::cerr << "校验和不匹配" << std::endl;
                delete[] dataBuffer;
                return 0;
            }
    
            // 读取帧尾
            uint8_t tail;
            bytesRead = serial.readBytes(&tail, 1, readTimeOut_ms);
            if (bytesRead != 1 || tail != FRAME_TAIL) 
            {
                // std::cerr << "帧尾不匹配" << std::endl;
                delete[] dataBuffer;
                return 0;
            }
    
            // 填充向量
            vec.resize(size);
            std::memcpy(vec.data(), dataBuffer, dataLength);
    
            delete[] dataBuffer;
            return 1;
        }
    
        // 检查是否连接
        bool connection() const 
        {
            return isConnected;
        }
        
        // 获取串口名称
        std::string getPortName() const 
        {
            return portName;
        }
        
        // 获取波特率
        unsigned int getBaudRate() const 
        {
            return baudRate;
        }

        /// @brief 清除串口缓存
        void clearBuffer()
        {
            auto length = serial.available();
            if (length > 0)
            {
                std::vector<uint8_t> buffer(length);
                if (serial.isDeviceOpen())
                {
                    serial.readBytes(buffer.data(),length);
                }
            }
        }
    
        // 禁用拷贝构造和赋值操作
        UartVectorPort(const UartVectorPort& other) = delete;
        UartVectorPort& operator=(const UartVectorPort& other) = delete;
    };
} // namespace cpp_tools